from typing import Optional
from moviepy import AudioFileClip, VideoFileClip
from PIL import Image, ImageOps, ImageEnhance, ImageFilter, ImageDraw, ImageFont
import os


def list_files(directory, extensions):
    return [
        os.path.join(directory, f)
        for f in os.listdir(directory)
        if os.path.splitext(f)[1].lower() in extensions
    ]
def safe_write_video(clip, output_path, codec="libx264", audio_codec="aac"):
    try:
        clip.write_videofile(output_path, codec=codec, audio_codec=audio_codec)
        print(f"已保存: {output_path}")
    except Exception as e:
        print(f"[错误] 写入视频文件失败: {e}")
        if os.path.exists(output_path):
            os.remove(output_path)
            print(f"[清理] 已删除损坏文件: {output_path}")

def iterative_video_crop(
        path: str,
        min_duration: float = 5.0,  # 最小保留时长（秒）
        step: float = 1.0,
        output_dir: Optional[str] = None,
):
    """
    迭代裁剪视频，每次starting_time递增1s，直到视频长度 <= min_duration。
    裁剪结果保存在原目录或指定输出目录。

    Args:
        path (`str`)：视频文件路径
        min_duration (`float`)：最小保留的视频时长（秒）
        output_dir (`str`, optional)：输出目录，默认为原文件所在目录
    """
    if not os.path.exists(path):
        raise FileNotFoundError(f"未找到视频文件: {path}")

    if output_dir is None:
        output_dir = os.path.dirname(path)

    # step = 1.0  # 初始裁剪起点
    start_time = step
    while True:

        with VideoFileClip(path) as clip:

            end_time = start_time + (clip.duration - start_time)
            if end_time > clip.duration:
                end_time = clip.duration

            cropped_clip = clip.subclipped(start_time, end_time)

            if cropped_clip.duration <= min_duration:
                print(f"[完成] 视频 已小于最小时长 {min_duration}s，停止处理。")
                break

            # 构建输出文件名
            filename = os.path.splitext(os.path.basename(path))[0]
            new_filename = f"{filename}_剪裁开始于{int(start_time)}s_剩余时长{int(cropped_clip.duration)}s.mp4"
            output_path = os.path.join(output_dir, new_filename)

            # 写入裁剪后的视频
            # 使用安全写入函数
            safe_write_video(cropped_clip, output_path, codec="libx264", audio_codec="aac")

            print(f"已保存: {output_path}")

            start_time += step  # 下一次裁剪起点递增
def safe_write_audio(clip, output_path, codec="libmp3lame"):
    try:
        clip.write_audiofile(output_path, codec=codec)
        print(f"已保存: {output_path}")
    except Exception as e:
        print(f"[错误] 写入音频失败: {e}")
        if os.path.exists(output_path):
            os.remove(output_path)
            print(f"[清理] 已删除损坏文件: {output_path}")

def iterative_audio_crop(
        path: str,
        min_duration: float = 5.0,  # 最小保留时长（秒）
        step: float = 1.0,
        output_dir: Optional[str] = None
):
    """
    迭代裁剪音频，每次starting_time递增1s，直到音频长度 <= min_duration。

    Args:
        path (`str`)：音频文件路径
        min_duration (`float`)：最小保留的音频时长（秒）
        output_dir (`str`, optional)：输出目录，默认为原文件所在目录
    """
    if not os.path.exists(path):
        raise FileNotFoundError(f"未找到音频文件: {path}")

    if output_dir is None:
        output_dir = os.path.dirname(path)

    # step = 1.0  # 初始裁剪起点
    start_time = step

    while True:
        with AudioFileClip(path) as clip:

            end_time = start_time + (clip.duration - start_time)
            if end_time > clip.duration:
                end_time = clip.duration

            cropped_clip = clip.subclipped(start_time, end_time)

            if cropped_clip.duration <= min_duration:
                print(f"[完成] 音频 已小于最小时长 {min_duration}s，停止处理。")
                break

            # 构建输出文件名
            filename = os.path.splitext(os.path.basename(path))[0]
            new_filename = f"{filename}_剪裁开始于{int(start_time)}s_剩余时长{int(cropped_clip.duration)}s.mp3"
            output_path = os.path.join(output_dir, new_filename)

            safe_write_audio(cropped_clip, output_path, codec="libmp3lame")


            print(f"已保存: {output_path}")

            start_time += step  # 下一次裁剪起点递增



from PIL import Image, ImageChops
import os


def process_image(
        path: str,
        output_dir: str = None,
        methods: list = None
):
    """
    对单张图片执行多种增强操作并保存。

    Args:
        path (str): 图片路径
        output_dir (str): 输出目录
        methods (list): 要应用的图像处理方法列表，如 ['flip', 'rotate_crop']
    """
    print(path)
    if methods is None:
        methods = ['flip',
                   # 'brightness',
                   # 'contrast',
                   # # 'grayscale',
                   # 'blur',
                   # 'sharpen',
                   # 'border',
                   # 'mosaic',
                   # 'watermark'
                   ]

    if output_dir is None:
        output_dir = os.path.dirname(path)
    filename = os.path.splitext(os.path.basename(path))[0]
    # 获取原始文件的扩展名
    original_ext = os.path.splitext(path)[1].lower()
    # 替换掉默认的 .jpg 为原始扩展名
    output_ext = original_ext if original_ext in ['.jpg', '.jpeg', '.png'] else '.jpg'  # 默认保持 jpg 防止不支持格式

    img = Image.open(path)

    idx = 1
    if img.mode == 'RGBA':
        img = img.convert('RGB')

    if 'flip' in methods:
        flipped_img = ImageOps.mirror(img)
        flipped_img.save(os.path.join(output_dir, f"{filename}_图片处理_水平镜像_{idx}{output_ext}"))
        idx += 1
    if 'brightness' in methods:
        brightened_img = adjust_brightness(img, factor=1.5)
        brightened_img.save(os.path.join(output_dir, f"{filename}_图片处理_亮度增强_{idx}{output_ext}"))
        idx += 1

    if 'contrast' in methods:
        contrasted_img = adjust_contrast(img, factor=1.5)
        contrasted_img.save(os.path.join(output_dir, f"{filename}_图片处理_对比度增强_{idx}{output_ext}"))
        idx += 1

    if 'grayscale' in methods:
        grayscale_img = to_grayscale(img)
        grayscale_img.save(os.path.join(output_dir, f"{filename}_图片处理_灰度化_{idx}{output_ext}"))
        idx += 1

    if 'blur' in methods:
        blurred_img = apply_blur(img, radius=2)
        blurred_img.save(os.path.join(output_dir, f"{filename}_图片处理_模糊效果_{idx}{output_ext}"))
        idx += 1

    if 'sharpen' in methods:
        sharpened_img = apply_sharpen(img)
        sharpened_img.save(os.path.join(output_dir, f"{filename}_图片处理_锐化效果_{idx}{output_ext}"))
        idx += 1

    if 'border' in methods:
        bordered_img = add_border(img, border_width=100, border_color="white")
        bordered_img.save(os.path.join(output_dir, f"{filename}_图片处理_添加边框_{idx}{output_ext}"))
        idx += 1

    if 'mosaic' in methods:
        mosaic_img = apply_mosaic(img, block_size=20)
        mosaic_img.save(os.path.join(output_dir, f"{filename}_图片处理_马赛克效果_{idx}{output_ext}"))
        idx += 1

    if 'watermark' in methods:
        # 确保有字体文件路径
        font_path = "path_to_your_font.ttf"  # 替换为实际字体文件路径
        watermarked_img = add_text_watermark(img, text="Sample Watermark", font_path=font_path, font_size=30,
                                             color=(255, 255, 255))
        watermarked_img.save(os.path.join(output_dir, f"{filename}_图片处理_添加水印_{idx}{output_ext}"))
        idx += 1

    # 辅助函数定义
def adjust_brightness(image, factor=1.0):
    enhancer = ImageEnhance.Brightness(image)
    return enhancer.enhance(factor)

def adjust_contrast(image, factor=1.0):
    enhancer = ImageEnhance.Contrast(image)
    return enhancer.enhance(factor)

def adjust_saturation(image, factor=1.0):
    enhancer = ImageEnhance.Color(image)
    return enhancer.enhance(factor)

def to_grayscale(image):
    return image.convert("L")

def apply_blur(image, radius=2):
    return image.filter(ImageFilter.GaussianBlur(radius))

def apply_sharpen(image):
    return image.filter(ImageFilter.SHARPEN)

def add_border(image, border_width=10, border_color="white"):
    width, height = image.size
    new_width = width + 2 * border_width
    new_height = height + 2 * border_width
    bordered_image = Image.new("RGB", (new_width, new_height), border_color)
    bordered_image.paste(image, (border_width, border_width))
    return bordered_image

def apply_mosaic(image, block_size=10):
    width, height = image.size
    small_image = image.resize((width // block_size, height // block_size), Image.Resampling.BILINEAR)
    mosaic_image = small_image.resize((width, height), Image.Resampling.NEAREST)
    return mosaic_image

def add_text_watermark(image, text, font_path, font_size=30, color=(255, 255, 255)):
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype(font_path, font_size)
    draw.text((10, 10), text, font=font, fill=color)
    return image


def split_long_video_to_clips(video_path, min_duration=20):
    """
    将一个长视频分割为多个最小长度为指定时长的视频片段。

    Args:
        video_path (str): 视频文件路径
        min_duration (float): 每个片段的最小持续时间（秒），默认为20秒

    Returns:
        list: 分割后的视频文件路径列表
    """
    from moviepy import VideoFileClip
    import os

    try:
        # 加载视频文件
        video = VideoFileClip(video_path)
        total_duration = video.duration
        clips = []

        # 计算可以分割的片段数量
        num_clips = int(total_duration // min_duration)

        # 如果视频时长不足一个片段的最小时间，则直接返回原视频
        if num_clips == 0:
            return [video_path]

        # 获取输出目录
        output_dir = os.path.dirname(video_path)
        video_filename = os.path.basename(video_path)
        video_name, video_ext = os.path.splitext(video_filename)

        # 分割视频为多个片段
        for i in range(num_clips):
            start_time = i * min_duration
            end_time = min((i + 1) * min_duration, total_duration)

            # 截取视频片段
            clip = video.subclipped(start_time, end_time)

            # 生成输出文件路径
            output_path = os.path.join(
                output_dir,
                f"{video_name}_片段{i + 1}_时长{int(clip.duration)}s{video_ext}"
            )

            # 保存视频片段
            clip.write_videofile(output_path, codec="libx264", audio_codec="aac")
            clips.append(output_path)

            print(f"已保存片段: {output_path} (时长: {clip.duration:.2f}秒)")

        # 处理剩余片段（如果剩余时间接近或超过min_duration，则也保存）
        remaining_start = num_clips * min_duration
        if remaining_start < total_duration:
            remaining_duration = total_duration - remaining_start
            # 如果剩余时间大于等于min_duration的一半，也保存为一个片段
            if remaining_duration >= min_duration / 2:
                clip = video.subclipped(remaining_start, total_duration)
                output_path = os.path.join(
                    output_dir,
                    f"{video_name}_片段{num_clips + 1}_时长{int(clip.duration)}s{video_ext}"
                )
                clip.write_videofile(output_path, codec="libx264", audio_codec="aac")
                clips.append(output_path)
                print(f"已保存片段: {output_path} (时长: {clip.duration:.2f}秒)")

        return clips

    except Exception as e:
        print(f"处理视频 {video_path} 时出错: {e}")
        return [video_path]


